package com.lightsh.download;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Map.Entry;
import com.lightsh.network.Utility;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * @author 
 * @param <T>
 * @warning 该类为下载图片的辅助类，进行图片下载并且转换成drawable，保存在静态对象中供使用
 */
public class DownloadImageHelper{
	/**
	 * 存储icon的drawable对象
	 * @author Shu
	 *
	 */
	
	private static final class LinkMap<K, V> extends LinkedHashMap<K, V>{
		private static final long serialVersionUID = 1L;
		
		public LinkMap(int initialCapacity, float loadFactor, boolean accessOrder){
			super(initialCapacity, loadFactor, accessOrder);
		}
		@Override
		protected boolean removeEldestEntry(Entry<K, V> eldest) {
			// 如果需要，则删除最旧的数据
//			boolean bRemove = size() >= MAX_BITMAP;
//			Log.e("LinkMap", "size:" + size() + ",bRemove:" + bRemove);
//			return bRemove;
			return size() >= MAX_BITMAP;
		}
		
		
	}
	private static final int MAX_BITMAP = 100;
	private static final LinkMap<String, Bitmap> mStaticBitmapMap = new LinkMap<String, Bitmap>(MAX_BITMAP, 0.7f, true);
	public static Bitmap searchBitmap(String key){
		return mStaticBitmapMap.get(key);
	}
	private static void addBitmap(String key, Bitmap bitmap){
		if(mStaticBitmapMap.containsKey(key)){
			// 已经存在
			return;
		}
		// 不需要手动移除
		mStaticBitmapMap.put(key, bitmap);
	}
	public static void clearBitmapsCache(){
		synchronized (mStaticBitmapMap) {
			Set<Entry<String, Bitmap>> entry = mStaticBitmapMap.entrySet();
			for(Entry<String, Bitmap> value : entry){
				Bitmap bitmap = value.getValue();
				if(bitmap != null && !bitmap.isRecycled()){
					bitmap.recycle();
					bitmap = null;
				}
			}
			mStaticBitmapMap.clear();
		}
	}
	
	// 每次重新获取图片信息的高度间隔
	public static final int REFRESH_LIST_ICON_DISTANCE = 5;
	
	public interface ImageLoaderInterface{
		/**
		 * 返回图片的标志(id值)
		 */
		public String getImageId();
		
		/**
		 * 返回图片的需要保存的下一个子文件夹,返回null表示保存在根文件夹.图片文件将会以下载url的后缀命名。
		 */
		public String getNextPath();
		
		/**
		 * 图片下载的URL(如果返回null则表示读取本地软件icon)
		 */
		public String getUrl();
	}
	
	/**
	 * 使用软件的名称来标志
	 */
	public static final String getImageViewTag(ImageLoaderInterface item){
		return item.getImageId();
	}
	
	
	private static final boolean DEBUG = true;
	private static final String TAG = "DownloadImageHelper";
	
	/**
	 * FIXME 图片存储的路径
	 */
	public static final String IMAGE_PATH_WITH_SD = "/sdcard/Android/data/com.lightsh.network/Image/";
    public static final String IMAGE_PATH_WITHOUT_SD = "/data/data/com.lightsh.network/AndroidCn/Image/";
	
	/**
	 * 每次请求时下载图片的最大数目
	 */
	private static final int DOWNLOAD_IMAGE_MAX_SIZE = 7;
	
	/**
	 * decode图片文件的尝试次数
	 */
	private static final int DECODE_IMAGE_TIMES = 3;
	public static final Bitmap tryDecodeBitmap(String bitmapFile){
		Bitmap bm = null;
		for(int j = 0; (j < DECODE_IMAGE_TIMES) && (bm == null); ++j){
			bm = BitmapFactory.decodeFile(bitmapFile);
		}
		return bm;
	}
    
	private Thread mBitmapLoadThread = null;
	
	// 按顺序下载大图，并且需要阻塞图片下载
	private Thread mBigBitmapLoadThread = null;

	private Context mContext;
    public DownloadImageHelper(Context context) {
    	mContext = context;
    }
    
    /** 
     * 该函数取消该类的所有回调事件,只有在拥有该类实例的activity销毁时需要调用
     * 
    */
    public void InterruptAll(){
    	// 需中断线程
    	if(mBitmapLoadThread != null){
    		if(mBitmapLoadThread.isAlive()){
    			mBitmapLoadThread.interrupt();
    		}
    		mBitmapLoadThread = null;
    	}
    	if(mBigBitmapLoadThread != null){
    		if(mBigBitmapLoadThread.isAlive()){
    			mBigBitmapLoadThread.interrupt();
    		}
    		mBigBitmapLoadThread = null;
    	}
    	
    	// 终止所有回调
    	mLoadImageCompleteListener = null;
    	mLoadImageErrorListener = null;
    	mLoadBigImageCompleteListener = null;
    	mLoadBigImageErrorListener = null;
    	
    }
    
    /**
     * 注意，这里需要是实现了ImageLoaderInterface的类型
     */
	public <T extends ImageLoaderInterface> void loadImageDrawable(
			final ArrayList<T> itemData, final int type) {
		int endIndex = itemData.size();
		if(endIndex > DOWNLOAD_IMAGE_MAX_SIZE) {
			endIndex = DOWNLOAD_IMAGE_MAX_SIZE;
		}
		loadImageDrawable(itemData, type, 0, endIndex);
	}
	
	// 下载图片，从startIndex开始到endIndex结束
	public <T extends ImageLoaderInterface> void loadImageDrawable(
			final ArrayList<T> itemData, final int type, final int startIndex, final int endIndex) {
		if (mBitmapLoadThread != null) {
			if (mBitmapLoadThread.isAlive()) {
				mBitmapLoadThread.interrupt();
			}
			mBitmapLoadThread = null;
		}
		mBitmapLoadThread = new Thread(new Runnable() {
			public void run() {
				for (int i = startIndex; i <= endIndex; i++) {
					if(i < 0 || i >= itemData.size()){
						return;
					}
					ImageLoaderInterface item = null;
					try {
						item = (ImageLoaderInterface)itemData.get(i);
						Bitmap bm = loadImage(item);
						if (Thread.interrupted()) {
							return;
						}
						if(bm != null){
							sendMessage(MSG_DOWNLOAD_IMAGE_FINISH, i, type, bm);
						} else {
							sendMessage(MSG_DOWNLOAD_IMAGE_ERROR, i, type, "load image fail");
						}
						
					} catch (Exception e) {
						if(DEBUG){
							Log.e(TAG, e.toString());
							e.printStackTrace();
						}
						if(item != null){
							File savefile = new File(getImageFullPath(item));
							if (savefile.exists())
								savefile.delete();
						}

						if (Thread.interrupted()) {
							return;
						}
						sendMessage(MSG_DOWNLOAD_IMAGE_ERROR, i, type, e.getMessage());
					}
				}
			}
		});
		mBitmapLoadThread.start();
	}
	
	/**
	 * 加载图片，如果失败返回null
	 * @throws IOException 
	 */
	private Bitmap loadImage(ImageLoaderInterface item) throws IOException{
		Bitmap bm = searchBitmap(item.getImageId());
		if(bm != null){
			return bm;
		}
		if(item.getUrl() == null){
			bm = loadLocalAppBitmap(item.getImageId());
			if(bm != null){
				DownloadImageHelper.addBitmap(item.getImageId(), bm);
			}
			return bm;
		}
		
		File savefile = new File(getImageFullPath(item));
		if (savefile.exists()) {
			// 图片已经存在,加载并返回
			bm = tryDecodeBitmap(savefile.getAbsolutePath());
			
			if (bm != null) {
				DownloadImageHelper.addBitmap(item.getImageId(), bm);
				return bm;
			} else {
				if (DEBUG) {
					Log.e(TAG, "decode fail:" + savefile.getAbsolutePath());
				}
				// 删除文件
				savefile.delete();
			}
		}		
		// 判断图片目录是否存在,不存在就创建
		File filePath = new File(savefile.getParent());
		if(!filePath.exists()){
			filePath.mkdirs();
		}
		
		HttpURLConnection conn = Utility.getConnection(item.getUrl());
		conn.setDoInput(true);
		conn.setRequestProperty("accept", "*/*");

		conn.connect();
		conn.getContentLength();
		InputStream inputStream = conn.getInputStream();

		if (!savefile.createNewFile()) {
			if (DEBUG) {
				Log.e(TAG, TAG + "create file fail:" + savefile.getAbsolutePath());
			}
			return null;
		}
		FileOutputStream fOut = null;
		fOut = new FileOutputStream(savefile);
		byte[] buf = new byte[2048];
		int nRead = 0;
		while (nRead != -1) {
			nRead = inputStream.read(buf);
			if (nRead != -1) {
				fOut.write(buf, 0, nRead);
			}
		}
		fOut.flush();
		fOut.close();
		inputStream.close();
		conn.disconnect();
		
		// 解码图片
		bm = tryDecodeBitmap(savefile.getAbsolutePath());
		if (bm != null) {
			DownloadImageHelper.addBitmap(item.getImageId(), bm);
			return bm;
		} else {
			if (DEBUG) {
				Log.e(TAG, "decode fail:" + savefile.getAbsolutePath());
			}
			// 删除文件
			savefile.delete();
			return null;
		}
	}
	
	/**
	 * 下载一张图片.
	 * 注意：startIndex是回调的时候用到的index值
	 */
	public void downloadBigImage(String url, String savePath, int startIndex){
		downloadBigImage(new String[]{url}, new String[]{savePath}, startIndex);
	}
	
	/**
	 * 下载一张图片.
	 * 注意：startIndex是回调的时候用到的index值,并非从urls的某一个位置开始
	 */
	public void downloadBigImage(final String[] urls, final String[] savePaths, final int startIndex){
    	if(mBigBitmapLoadThread != null){
    		if(mBigBitmapLoadThread.isAlive()){
    			mBigBitmapLoadThread.interrupt();
    		}
    		mBigBitmapLoadThread = null;
    	}
    	mBigBitmapLoadThread = new Thread(new Runnable() {
            public void run() {
				if (urls.length != savePaths.length) {
					return;
				}
				int nSize = urls.length;
				for (int i = 0; i < nSize; ++i) {
					try {
						Bitmap bm = loadBigImage(urls[i], savePaths[i], startIndex + i, (startIndex == 0 && nSize == 1));
						if (Thread.interrupted()) {
							return;
						}
						if (bm != null) {
							sendMessage(MSG_DOWNLOAD_BIG_IMAGE_FINISH,
									startIndex + i, 0, bm);
						} else {
							sendMessage(MSG_DOWNLOAD_BIG_IMAGE_ERROR,
									startIndex + i, 0, "load big image fail");
						}
					} catch (Exception e) {
						if (DEBUG) {
							Log.e(TAG, e.toString());
							e.printStackTrace();
						}
						// 删除文件
						File savefile = new File(savePaths[i]);
						if (savefile.exists()) {
							savefile.delete();
						}
						if (Thread.interrupted()) {
							return;
						}
						sendMessage(MSG_DOWNLOAD_BIG_IMAGE_ERROR, startIndex + i, 0, e.getMessage());
					}
				}
                
            }
        });
    	mBigBitmapLoadThread.start();
    }
	
	private Bitmap loadBigImage(String url, String savePath, int i, boolean bLeftTemp) throws IOException {
		Bitmap bm = null;
		File savefile = new File(savePath);
    	if( savefile.exists() ){
    		bm = tryDecodeBitmap(savePath);
    		if(bm != null){
    			return bm;
    		} else {
    			if(!bLeftTemp){
    				savefile.delete();
    			} else {
    				return null;
    			}
    		}
    	}
		HttpURLConnection conn = Utility.getConnection(url);
		conn.setDoInput(true);
		conn.setRequestProperty("accept", "*/*");
		conn.connect();
		InputStream inputStream = conn.getInputStream();
		File filePath = new File(savefile.getParent());
		if(!filePath.exists()){
			filePath.mkdirs();
		}
		savefile.createNewFile();
		FileOutputStream fOut = null;

		fOut = new FileOutputStream(savefile);
		
		byte[] buf = new byte[2048];
		int nRead = 0;
		while (nRead != -1) {
			nRead = inputStream.read(buf);
			if (nRead != -1) {
				fOut.write(buf, 0, nRead);
			}
		}
		fOut.flush();
		fOut.close();
		inputStream.close();
		conn.disconnect();
		
		bm = tryDecodeBitmap(savePath);
		if(bm == null){
			savefile.delete();
			if (DEBUG) {
				Log.e(TAG, "decode fail:" + savefile.getAbsolutePath());
			}
		}
		return bm;
	}
	
	
	
	private static final int MSG_DOWNLOAD_IMAGE_FINISH = 1;
	private static final int MSG_DOWNLOAD_IMAGE_ERROR = -1;
	
	private static final int MSG_DOWNLOAD_BIG_IMAGE_FINISH = 2;
	private static final int MSG_DOWNLOAD_BIG_IMAGE_ERROR = -2;
	
	
	private Handler mHandler = new Handler(){
		public void handleMessage(Message msg){
			switch(msg.what){
			case MSG_DOWNLOAD_IMAGE_FINISH:{
				if(mLoadImageCompleteListener != null){
					mLoadImageCompleteListener.onLoadComplete(msg.arg1, msg.arg2, msg.obj);
				}
			}
				break;
			case MSG_DOWNLOAD_IMAGE_ERROR:{
				if(mLoadImageErrorListener != null){
					mLoadImageErrorListener.onLoadError(msg.arg1, msg.arg2, msg.obj);
				}
			}
				break;
			case MSG_DOWNLOAD_BIG_IMAGE_FINISH:{
				if(mLoadBigImageCompleteListener != null){
					mLoadBigImageCompleteListener.onLoadBigImageComplete(msg.arg1, msg.obj);
				}
			}
				break;
			case MSG_DOWNLOAD_BIG_IMAGE_ERROR:{
				if(mLoadBigImageErrorListener != null){
					mLoadBigImageErrorListener.onLoadBigImageError(msg.arg1, msg.obj);
				}
			}
				break;
			}
		}
	};
	
	/**
	 * 获取合适的图片地址
	 */
	private static final String getImageFullPath(ImageLoaderInterface item){
		return getImageFullPath(item.getNextPath(), item.getUrl());
	}
	public static final String getImageFullPath(String nextPath, String url){
		String rootPath = getImageFilePath();
		if(nextPath != null && nextPath.length() > 0){
			rootPath += nextPath + "/";
		}
		rootPath += getFileNameFromUrl(url);
		return rootPath;
	}
	
	private static final String getFileNameFromUrl(String url){
    	try{
    		return url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
    	}catch(Exception e){
    		if(DEBUG){
    			e.printStackTrace();
    		}
    		return "errorName";
    	}
    }
	
    
    private void sendMessage(int what, int arg1, int arg2, Object obj){
        Message msg = mHandler.obtainMessage(what, arg1, arg2, obj);
        mHandler.sendMessage(msg);
    }

    /**
     * icon图片下载完成的回调函数
     */
    private OnLoadImageCompleteListener mLoadImageCompleteListener;

    public interface OnLoadImageCompleteListener {
        void onLoadComplete(int position, int type ,Object bitmap);
    }

    public void setOnLoadImageCompleteListener(OnLoadImageCompleteListener listener) {
        mLoadImageCompleteListener = listener;
    }
    
    /**
     * icon图片下载失败
     */
    private OnLoadImageErrorListener mLoadImageErrorListener;
    public interface OnLoadImageErrorListener{
        void onLoadError(int position, int type, Object errMsg);
    }
    public void setOnLoadImageErrorListener( OnLoadImageErrorListener listener ){
    	mLoadImageErrorListener = listener;
    }
    
    /**
     * 大图下载完成
     */
    private OnLoadBigImageCompleteListener mLoadBigImageCompleteListener;

    public interface OnLoadBigImageCompleteListener {
        void onLoadBigImageComplete(int index, Object bitmap);
    }

    public void setOnLoadBigImageCompleteListener(OnLoadBigImageCompleteListener listener) {
    	mLoadBigImageCompleteListener = listener;
    }
    
    /**
     * 大图下载失败
     */
    private OnLoadBigImageErrorListener mLoadBigImageErrorListener;

    public interface OnLoadBigImageErrorListener {
        void onLoadBigImageError(int index, Object errMsg);
    }

    public void setOnLoadBigImageErrorListener(OnLoadBigImageErrorListener listener) {
    	mLoadBigImageErrorListener = listener;
    }
    
    public Bitmap loadLocalAppBitmap(String packageName){
		try{
			PackageManager pm = mContext.getPackageManager();
			Drawable drawable = pm.getApplicationIcon(packageName);
			if(drawable != null){
				return drawable2Bitmap(drawable);
			}
		}catch(NameNotFoundException e){
		}
		return null;
	}
    
    public static final Bitmap drawable2Bitmap(Drawable drawable){
		Bitmap bitmap = Bitmap .createBitmap(
							drawable.getIntrinsicWidth(),
							drawable.getIntrinsicHeight(),
							drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
		drawable.draw(canvas);
		return bitmap;
    }
    
    public static final Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundX, float roundY) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundX, roundY, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;     
    }
    
    /**
     * 获得当前所用的图片存储路径
     * 
     * @return，当前图片存储路径
     */
	public static String getImageFilePath(){
		if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
			return IMAGE_PATH_WITH_SD;
		}else {
			return IMAGE_PATH_WITHOUT_SD;
		}
	}
}